package com.bootdo.common.geneseq.range.impl.db;

import javax.sql.DataSource;

import com.bootdo.common.geneseq.exception.SeqException;
import com.bootdo.common.geneseq.range.SeqRange;
import com.bootdo.common.geneseq.range.SeqRangeMgr;
import com.bootdo.common.service.GeneseqService;
import com.smart.common.utils.ApplicationContextProvider;

public class DbSeqRangeMgr implements SeqRangeMgr {
	
//	@Autowired
//	private GeneseqService geneseqService;

    /**
     * 区间步长
     */
    private int  step       = 1000;
    /**
     * 区间起始位置，真实从stepStart+1开始
     */
    private long stepStart  = 0;
    /**
     * 获取区间失败重试次数
     */
    private int  retryTimes = 100;
    /**
     * DB来源
     */
    private DataSource dataSource;
    /**
     * 表名，默认range
     */
    private String tableName = "range";

    @Override
    public SeqRange nextRange(String serviceCode) throws SeqException {
        if (isEmpty(serviceCode)) {
            throw new SecurityException("[DbSeqRangeMgr-nextRange] serviceCode is empty.");
        }

        Long oldValue;
        Long newValue;

        GeneseqService geneseqService = ApplicationContextProvider.getBean(GeneseqService.class);
        for (int i = 0; i < getRetryTimes(); i++) {
            oldValue = geneseqService.selectRange(serviceCode);
            if (null == oldValue) {
                //区间不存在，重试
                continue;
            }

            newValue = oldValue + getStep();
            int updateRange = geneseqService.updateRange(newValue,oldValue, serviceCode);
            if (updateRange > 0) {
                
            	return new SeqRange(oldValue + 1, newValue);
            }
            //else 失败重试
        }

        throw new SeqException("Retried too many times, retryTimes = " + getRetryTimes());
    }


    private boolean isEmpty(String str) {
        return null == str || str.trim().length() == 0;
    }

    ////////getter and setter

    public int getStep() {
        return step;
    }

    public void setStep(int step) {
        this.step = step;
    }

    public long getStepStart() {
        return stepStart;
    }

    public void setStepStart(long stepStart) {
        this.stepStart = stepStart;
    }

    public int getRetryTimes() {
        return retryTimes;
    }

    public void setRetryTimes(int retryTimes) {
        this.retryTimes = retryTimes;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }
    
}
